#ifndef SRC_MPI_MPI_UTIL
#define SRC_MPI_MPI_UTIL

#include <mpi.h>
#include <string>
#include <vector>

void MPI_Send_String(const std::string &buf, int dest, int tag, MPI_Comm comm);
void MPI_Send_Strings(const std::vector<std::string> &buffs, int dest, int tag,
                      MPI_Comm comm);

void MPI_Recv_String(std::string &buf, int src, int tag, MPI_Comm comm);
void MPI_Recv_Strings(std::vector<std::string> &buffs, int vec_size, int src,
                      int tag, MPI_Comm comm);
void MPI_PackRecv_Strings(std::vector<std::string> &buffs, int vec_size,
                          int src, int tag, MPI_Comm comm);
void MPI_MultiPackRecv_Strings(std::vector<std::string> &buffs, int vec_size,
                               int src, int tag, MPI_Comm comm);

void MPI_Bcast_String(std::string &buf, int root, MPI_Comm comm);
void MPI_Bcast_Strings(std::vector<std::string> &buffs, int root,
                       MPI_Comm comm);
void MPI_PackBcast_Strings(std::vector<std::string> &buffs, int root,
                           MPI_Comm comm);

void MPI_Isendrecv_String_replace(std::string &buf, int dest, int tag_send,
                                  int src, int tag_recv, MPI_Comm comm);
void MPI_Sendrecv_String_replace(std::string &buf, int dest, int tag_send,
                                 int src, int tag_recv, MPI_Comm comm);
// overload (beecause method signatures are the same)
void MPI_Sendrecv_String_replace(std::vector<std::string> &buffs, int dest,
                                 int tag_send, int src, int tag_recv,
                                 MPI_Comm comm);

//* Non-blocking
void MPI_Isend_String(const std::string &buf, int dest, int tag, MPI_Comm comm,
                      MPI_Request *req);
void MPI_Isend_Strings(const std::vector<std::string> &buffs, int dest, int tag,
                       MPI_Comm comm, MPI_Request *req);
void MPI_PackIsend_Strings(const std::vector<std::string> &buffs,
                           std::string &pack_buff, int *size_buff, int dest,
                           int tag, MPI_Comm comm, MPI_Request *req);
void MPI_PackSend_Strings(const std::vector<std::string> &buffs,
                          std::string &pack_buff, int *size_buff, int dest,
                          int tag, MPI_Comm comm);
void MPI_PackIsend_Strings(const std::vector<std::string> &buffs,
                           std::vector<std::string> &pack_buffs,
                           std::vector<std::vector<int>> &size_buffs, int dest,
                           int tag, MPI_Comm comm, MPI_Request *req);
void MPI_PackIbcast_Strings(std::vector<std::string> &buffs, int root,
                            MPI_Comm comm);

#endif /* SRC_MPI_MPI_UTIL */
